/**
 * Copyright (C) 2010, 2011 Neofonie GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package eu.dicodeproject.analysis.restapi;

import java.util.Calendar;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.xml.bind.DatatypeConverter;

/**
 * Utility class for TwitterController.
 */
public class TwitterControllerUtil {

  public static void addZeros(Set<String> required, Map<String,Integer> map) {
    for (String r : required) {
      if (!map.containsKey(r)) {
        map.put(r, 0);
      }
    }
  }

  /**
   * @param dateType a string specifying the type of date contained in the dateMap (can be "year", "yearMonth", "yearMonthDay", "hour")
   * @param start earliest date in the result
   * @param stop EXCLUSIVE latest date in the result
   * @return a sorted set with all dates in the required range of the required type
   */
  public static SortedSet<String> getAllDates(String dateType, String start, String stop) {
    if (dateType.equals("year") || dateType.equals("yearMonth") || dateType.equals("yearMonthDay")) {
      return getCompleteDates(dateType, start, stop);
    }
    else if (dateType.equals("hour")) {
      return getHours();
    }
    else {
      throw new IllegalArgumentException("unknown dateType: "+dateType);
    }
  }

  private static SortedSet<String> getCompleteDates(String dateType, String start, String stop) {
    Calendar cal = Calendar.getInstance();
    if (start == null) {
      start = String.valueOf(cal.get(Calendar.YEAR)-1);  // default is one year back from today
    }
    int startYear = Integer.valueOf(start.substring(0, 4));
    if (stop == null) {
      stop = DatatypeConverter.printDate(cal).substring(0, 10);  // XSD date without time zone addition
    }
    int endYear = Integer.valueOf(stop.substring(0,4));

    SortedSet<String> allDates = new TreeSet<String>();

    // add year if 0
    for (int y=startYear; y<=endYear; y++) {
      String yearString = String.valueOf(y);
      if (needsToBeAdded("year", dateType, yearString, start, stop)) {
        allDates.add(yearString);
      }
      cal.set(Calendar.YEAR, y);

      // add year+month if 0
      for (int m=1; m<=cal.getActualMaximum(Calendar.MONTH)+1; m++) {  // Calendar.JANUARY == 0
        String monthString = String.valueOf(m);
        if (monthString.length() == 1) {
          monthString = "0"+monthString;
        }
        String yearMonthString = yearString + "-" + monthString;
        if (needsToBeAdded("yearMonth", dateType, yearMonthString, start, stop)) {
          allDates.add(yearMonthString);
        }
        cal.set(Calendar.MONTH, m-1);  // Calendar.JANUARY == 0

        // add year+month+day if 0
        for (int d=1; d<=cal.getActualMaximum(Calendar.DAY_OF_MONTH); d++) {
          String dayString = String.valueOf(d);
          if (dayString.length() == 1) {
            dayString = "0"+dayString;
          }
          String yearMonthDayString = yearString + "-" + monthString + "-" + dayString;
          if (needsToBeAdded("yearMonthDay", dateType, yearMonthDayString, start, stop)) {
            allDates.add(yearMonthDayString);
          }
        }
      }
    }
    return allDates;
  }

  private static boolean needsToBeAdded(String expectedDateType, String actualDateType,
      String current, String start, String stop) {
    if (!expectedDateType.equals(actualDateType)) {
      return false; // wrong dateType: don't care
    }
    if (start != null && current.compareTo(start) < 0) {
      return false; // value is too small
    }
    if (stop != null && current.compareTo(stop) >= 0) {
      return false; // value is too big
    }
    return true;
  }

  private static SortedSet<String> getHours() {
    SortedSet<String> s = new TreeSet<String>();
    for (int h=0; h<24; h++) {
      String hourString = String.valueOf(h);
      if (h < 10) {
        hourString = "0" + hourString;
      }
      s.add(hourString);
    }
    return s;
  }
}
